#!/usr/bin/env python

"""
Jenkins runs this script to perform a test of an e3sm
test suite. Essentially, a wrapper around create_test and
wait_for_tests that handles cleanup of old test results and
ensures that the batch system is left in a clean state.
"""

from standard_script_setup import *

import CIME.wait_for_tests
from CIME.utils import expect
from CIME.XML.machines import Machines
from jenkins_generic_job import jenkins_generic_job

# Don't know if this belongs here longterm
MACHINES_THAT_MAINTAIN_BASELINES = ("melvin", "sandiatoss3")

###############################################################################
def parse_command_line(args, description):
###############################################################################
    parser = argparse.ArgumentParser(
usage="""\n{0} [-g] [-d] [--verbose]
OR
{0} --help

\033[1mEXAMPLES:\033[0m
    \033[1;32m# Run the tests and compare baselines \033[0m
    > {0}
    \033[1;32m# Run the tests, compare baselines, and update dashboard \033[0m
    > {0} -d
    \033[1;32m# Run the tests, generating a full set of baselines (useful for first run on a machine) \033[0m
    > {0} -g
""".format(os.path.basename(args[0])),

description=description,

formatter_class=argparse.ArgumentDefaultsHelpFormatter
)

    CIME.utils.setup_standard_logging_options(parser)

    default_baseline = CIME.utils.get_current_branch(repo=CIME.utils.get_cime_root())
    if default_baseline is not None:
        default_baseline = default_baseline.replace(".", "_").replace("/", "_") # Dots or slashes will mess things up

    parser.add_argument("-g", "--generate-baselines", action="store_true",
                        help="Generate baselines")

    parser.add_argument("--baseline-compare",
                        help="Do baseline comparisons (yes/no)")

    parser.add_argument("--submit-to-cdash", action="store_true",
                        help="Send results to CDash")

    parser.add_argument("--update-success", action="store_true",
                        help="Record test success in baselines. Only the nightly process should use this in general.")

    parser.add_argument("--no-batch", action="store_true",
                        help="Do not use batch system even if on batch machine")

    parser.add_argument("-c", "--cdash-build-name",
                        help="Build name to use for CDash submission. Default will be <TEST_SUITE>_<BRANCH>_<COMPILER>")

    parser.add_argument("-p", "--cdash-project", default=CIME.wait_for_tests.E3SM_MAIN_CDASH,
                        help="The name of the CDash project where results should be uploaded")

    parser.add_argument("-b", "--baseline-name", default=default_baseline,
                        help="Baseline name for baselines to use. Also impacts dashboard job name. Useful for testing a branch other than next or master")

    parser.add_argument("-B", "--baseline-root",
                        help="Baseline area for baselines to use. Default will be config_machine value for machine")

    parser.add_argument("-O", "--override-baseline-name",
                        help="Force comparison with these baseines without impacting dashboard or test-id.")

    parser.add_argument("-t", "--test-suite",
                        help="Override default e3sm test suite that will be run")

    parser.add_argument("-r", "--scratch-root",
                        help="Override default e3sm scratch root. Use this to avoid conflicting with other jenkins jobs")

    parser.add_argument("--cdash-build-group", default=CIME.wait_for_tests.CDASH_DEFAULT_BUILD_GROUP,
                        help="The build group to be used to display results on the CDash dashboard.")

    parser.add_argument("-j", "--parallel-jobs", type=int, default=None,
                        help="Number of tasks create_test should perform simultaneously. Default "
                        "will be min(num_cores, num_tests).")

    parser.add_argument("--walltime",
                        help="Force a specific walltime for all tests.")

    parser.add_argument("-m", "--machine",
                        help="The machine for which to build tests, this machine must be defined"
                        " in the config_machines.xml file for the given model. "
                        "Default is to match the name of the machine in the test name or "
                        "the name of the machine this script is run on to the "
                        "NODENAME_REGEX field in config_machines.xml. This option is highly "
                        "unsafe and should only be used if you know what you're doing.")

    parser.add_argument("--compiler",
                        help="Compiler to use to build cime.  Default will be the default defined for the machine.")

    args = CIME.utils.parse_args_and_handle_standard_logging_options(args, parser)

    expect(not (args.submit_to_cdash and args.generate_baselines),
           "Does not make sense to use --generate-baselines and --submit-to-cdash together")
    expect(not (args.cdash_build_name is not None and not args.submit_to_cdash),
           "Does not make sense to use --cdash-build-name without --submit-to-cdash")
    expect(not (args.cdash_project is not CIME.wait_for_tests.E3SM_MAIN_CDASH and not args.submit_to_cdash),
           "Does not make sense to use --cdash-project without --submit-to-cdash")
    expect (args.baseline_compare in [None, "yes", "no"],
            "Valid args for --baseline-compare are 'yes' or 'no'")

    machine = Machines(machine=args.machine)
    machine_name = machine.get_machine_name()

    args.machine = machine
    args.test_suite = machine.get_value("TESTS") if args.test_suite is None else args.test_suite
    default_maintain_baselines = machine_name in MACHINES_THAT_MAINTAIN_BASELINES
    args.baseline_compare = default_maintain_baselines if args.baseline_compare is None else args.baseline_compare == "yes"
    args.scratch_root = machine.get_value("CIME_OUTPUT_ROOT") if args.scratch_root is None else args.scratch_root
    args.compiler = machine.get_default_compiler() if args.compiler is None else args.compiler

    expect(args.baseline_name is not None,
           "Failed to probe baseline_name from git branch, please provide one. It is essential for formulating the test-id even if baseline comparisons are not being done")

    if args.override_baseline_name is None:
        args.override_baseline_name = args.baseline_name

    return args.generate_baselines, args.submit_to_cdash, args.no_batch, args.baseline_name, args.cdash_build_name, \
        args.cdash_project, args.test_suite, args.cdash_build_group, args.baseline_compare, args.scratch_root, args.parallel_jobs, args.walltime, args.machine, args.compiler, args.override_baseline_name, args.baseline_root, args.update_success

###############################################################################
def _main_func(description):
###############################################################################
    generate_baselines, submit_to_cdash, no_batch, baseline_name, cdash_build_name, cdash_project, test_suite, cdash_build_group, baseline_compare, scratch_root, parallel_jobs, walltime, machine, compiler, real_baseline_name, baseline_root, update_success = \
        parse_command_line(sys.argv, description)

    sys.exit(0 if jenkins_generic_job(generate_baselines, submit_to_cdash, no_batch, baseline_name, cdash_build_name, cdash_project, test_suite, cdash_build_group, baseline_compare, scratch_root, parallel_jobs, walltime, machine, compiler, real_baseline_name, baseline_root, update_success)
             else CIME.utils.TESTS_FAILED_ERR_CODE)

###############################################################################

if (__name__ == "__main__"):
    _main_func(__doc__)
